using System;
using System.ComponentModel;
using System.Configuration.Install;

using System.Runtime.InteropServices;

using System.IO;

namespace TaskService.CustomInstallActions
{
    /// <summary>
    /// Creates the shout cuts for the application installation.
    /// </summary>
   [RunInstaller(true)]
   public partial class CreateShortcuts : Installer
   {

      #region SHGetSpecialFolderPath
      [DllImport("shell32.dll")]
      static extern bool SHGetSpecialFolderPath (IntPtr hwndOwner, [Out] System.Text.StringBuilder lpszPath, int nFolder, bool fCreate);

      private enum CSIDL
      {
         CSIDL_ADMINTOOLS = 0x0030,
         CSIDL_ALTSTARTUP = 0x001d,
         CSIDL_APPDATA = 0x001a,
         CSIDL_BITBUCKET = 0x000a,
         CSIDL_CDBURN_AREA = 0x003b,
         CSIDL_COMMON_ADMINTOOLS = 0x002f,
         CSIDL_COMMON_ALTSTARTUP = 0x001e,
         CSIDL_COMMON_APPDATA = 0x0023,
         CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019,
         CSIDL_COMMON_DOCUMENTS = 0x002e,
         CSIDL_COMMON_FAVORITES = 0x001f,
         CSIDL_COMMON_MUSIC = 0x0035,
         CSIDL_COMMON_OEM_LINKS = 0x003a,
         CSIDL_COMMON_PICTURES = 0x0036,
         CSIDL_COMMON_PROGRAMS = 0X0017,
         CSIDL_COMMON_STARTMENU = 0x0016,
         CSIDL_COMMON_STARTUP = 0x0018,
         CSIDL_COMMON_TEMPLATES = 0x002d,
         CSIDL_COMMON_VIDEO = 0x0037,
         CSIDL_COMPUTERSNEARME = 0x003d,
         CSIDL_CONNECTIONS = 0x0031,
         CSIDL_CONTROLS = 0x0003,
         CSIDL_COOKIES = 0x0021,
         CSIDL_DESKTOP = 0x0000,
         CSIDL_DESKTOPDIRECTORY = 0x0010,
         CSIDL_DRIVES = 0x0011,
         CSIDL_FAVORITES = 0x0006,
         CSIDL_FLAG_CREATE = 0x8000,
         CSIDL_FLAG_DONT_VERIFY = 0x4000,
         CSIDL_FLAG_MASK = 0xFF00,
         CSIDL_FLAG_NO_ALIAS = 0x1000,
         CSIDL_FLAG_PER_USER_INIT = 0x0800,
         CSIDL_FONTS = 0x0014,
         CSIDL_HISTORY = 0x0022,
         CSIDL_INTERNET = 0x0001,
         CSIDL_INTERNET_CACHE = 0x0020,
         CSIDL_LOCAL_APPDATA = 0x001c,
         CSIDL_MYDOCUMENTS = 0x000c,
         CSIDL_MYMUSIC = 0x000d,
         CSIDL_MYPICTURES = 0x0027,
         CSIDL_MYVIDEO = 0x000e,
         CSIDL_NETHOOD = 0x0013,
         CSIDL_NETWORK = 0x0012,
         CSIDL_PERSONAL = 0x0005,
         CSIDL_PRINTERS = 0x0004,
         CSIDL_PRINTHOOD = 0x001b,
         CSIDL_PROFILE = 0x0028,
         CSIDL_PROGRAM_FILES = 0x0026,
         CSIDL_PROGRAM_FILES_COMMON = 0x002b,
         CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c,
         CSIDL_PROGRAM_FILESX86 = 0x002a,
         CSIDL_PROGRAMS = 0x0002,
         CSIDL_RECENT = 0x0008,
         CSIDL_RESOURCES = 0x0038,
         CSIDL_RESOURCES_LOCALIZED = 0x0039,
         CSIDL_SENDTO = 0x0009,
         CSIDL_STARTMENU = 0x000b,
         CSIDL_STARTUP = 0x0007,
         CSIDL_SYSTEM = 0x0025,
         CSIDL_SYSTEMX86 = 0x0029,
         CSIDL_TEMPLATES = 0x0015,
         CSIDL_WINDOWS = 0x0024
      }


      #endregion SHGetSpecialFolderPath

      /// <summary>
      /// Initializes a new instance of the <see cref="CreateShortcuts"/> class.
      /// </summary>
      public CreateShortcuts ()
      {
         InitializeComponent();

         //System.Diagnostics.Debugger.Launch();
      }

      #region Private Variables
      
      private const string DESKTOP_SHORTCUT_PARAM = "DesktopShortcut";
      private const string SHORTCUT_MENU_SHORTCUT_PARAM = "StartMenuShortcut";
      private const string QUICK_LAUNCH_SHORTCUT_PARAM = "QuickLaunchShortcut";
      private const string ALL_USER_PARAM = "AllUsers";
      private const string PRODUCT_NAME_PARAM = "ProductName";

      private const string LOG_FOLDER_LINK = "Guadagno Task Scheduler Log files.lnk";
      private const string PLUGIN_FOLDER_LINK = "Guadagno Task Scheduler Plug-ins.lnk";
      private const string TEST_LINK = "Task Plug-in Test Application.lnk";

      private string _installPath = "";
      private string _productName = "";

      private bool _createDesktopShortcut = true;
      private bool _createStartMenuShortcut = true;
      private bool _createQuickLaunchShortcut = true;
      private bool _installAllUsers;

      #endregion Private Variables

      #region Installer Implementation

      /// <summary>
      /// When overridden in a derived class, performs the installation.
      /// </summary>
      /// <param name="stateSaver">An <see cref="T:System.Collections.IDictionary"/> used to save information needed to perform a commit, rollback, or uninstall operation.</param>
      /// <exception cref="T:System.ArgumentException">
      /// The <paramref name="stateSaver"/> parameter is null.
      /// </exception>
      /// <exception cref="T:System.Exception">
      /// An exception occurred in the <see cref="E:System.Configuration.Install.Installer.BeforeInstall"/> event handler of one of the installers in the collection.
      /// -or-
      /// An exception occurred in the <see cref="E:System.Configuration.Install.Installer.AfterInstall"/> event handler of one of the installers in the collection.
      /// </exception>
      public override void Install (System.Collections.IDictionary stateSaver)
      {
         base.Install(stateSaver);

         initializeVariables();
         createShortcut(_installPath, LOG_FOLDER_LINK);
         createShortcut(_installPath, PLUGIN_FOLDER_LINK);
         createShortcut(_installPath, TEST_LINK);

      }

      /// <summary>
      /// When overridden in a derived class, completes the install transaction.
      /// </summary>
      /// <param name="savedState">An <see cref="T:System.Collections.IDictionary"/> that contains the state of the computer after all the installers in the collection have run.</param>
      /// <exception cref="T:System.ArgumentException">
      /// The <paramref name="savedState"/> parameter is null.
      /// -or-
      /// The saved-state <see cref="T:System.Collections.IDictionary"/> might have been corrupted.
      /// </exception>
      /// <exception cref="T:System.Configuration.Install.InstallException">
      /// An exception occurred during the <see cref="M:System.Configuration.Install.Installer.Commit(System.Collections.IDictionary)"/> phase of the installation. This exception is ignored and the installation continues. However, the application might not function correctly after the installation is complete.
      /// </exception>
      public override void Commit (System.Collections.IDictionary savedState)
      {
         base.Commit(savedState);
      }

      /// <summary>
      /// When overridden in a derived class, restores the pre-installation state of the computer.
      /// </summary>
      /// <param name="savedState">An <see cref="T:System.Collections.IDictionary"/> that contains the pre-installation state of the computer.</param>
      /// <exception cref="T:System.ArgumentException">
      /// The <paramref name="savedState"/> parameter is null.
      /// -or-
      /// The saved-state <see cref="T:System.Collections.IDictionary"/> might have been corrupted.
      /// </exception>
      /// <exception cref="T:System.Configuration.Install.InstallException">
      /// An exception occurred during the <see cref="M:System.Configuration.Install.Installer.Rollback(System.Collections.IDictionary)"/> phase of the installation. This exception is ignored and the rollback continues. However, the computer might not be fully reverted to its initial state after the rollback completes.
      /// </exception>
      public override void Rollback (System.Collections.IDictionary savedState)
      {
         base.Rollback(savedState);

         initializeVariables();
         removeShortcut(LOG_FOLDER_LINK);
         removeShortcut(PLUGIN_FOLDER_LINK);
         removeShortcut(TEST_LINK);
      }

      /// <summary>
      /// When overridden in a derived class, removes an installation.
      /// </summary>
      /// <param name="savedState">An <see cref="T:System.Collections.IDictionary"/> that contains the state of the computer after the installation was complete.</param>
      /// <exception cref="T:System.ArgumentException">
      /// The saved-state <see cref="T:System.Collections.IDictionary"/> might have been corrupted.
      /// </exception>
      /// <exception cref="T:System.Configuration.Install.InstallException">
      /// An exception occurred while uninstalling. This exception is ignored and the uninstall continues. However, the application might not be fully uninstalled after the uninstallation completes.
      /// </exception>
      public override void Uninstall (System.Collections.IDictionary savedState)
      {
         base.Uninstall(savedState);

         initializeVariables();
         removeShortcut(LOG_FOLDER_LINK);
         removeShortcut(PLUGIN_FOLDER_LINK);
         removeShortcut(TEST_LINK);
      }

      #endregion Installer Implementation

      #region Private Methods

      #region createShortcut

      /// <summary>
      /// Creates the shortcut.
      /// </summary>
      /// <param name="pathFrom">The path from.</param>
      /// <param name="filename">The filename.</param>
      private void createShortcut (string pathFrom, string filename)
      {

         string fullFilename = Path.Combine(pathFrom, filename);

         if (_createDesktopShortcut)
         {
            string destination = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), filename);
            if (_installAllUsers)
            {
               destination = Path.Combine(getSpecialFolderPath(CSIDL.CSIDL_COMMON_DESKTOPDIRECTORY), filename);
            }
            File.Copy(fullFilename, destination,true);
         }

         if (_createStartMenuShortcut)
         {

            string destination;

            if (_installAllUsers)
            {
               string folder = Path.Combine(getSpecialFolderPath(CSIDL.CSIDL_COMMON_STARTMENU), "Programs");
               folder = Path.Combine(folder, _productName);
               Directory.CreateDirectory(folder);
               destination = Path.Combine(folder, filename);
            }
            else
            {
               string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs");
               folder = Path.Combine(folder, _productName);
               Directory.CreateDirectory(folder);
               destination = Path.Combine(folder, filename);
            }

            File.Copy(fullFilename, destination, true);
         }

         if (_createQuickLaunchShortcut)
         {
            string quickLaunch = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Microsoft\Internet Explorer\Quick Launch");
            string destination = Path.Combine(quickLaunch, filename);
            File.Copy(fullFilename, destination, true);
         }

      }

      #endregion createShortcut

      #region removeShortcut

      /// <summary>
      /// Removes the shortcut.
      /// </summary>
      /// <param name="filename">The filename.</param>
      private void removeShortcut (string filename)
      {
         
         if (_createDesktopShortcut)
         {
            string destination = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), filename);
            if (_installAllUsers)
            {
               destination = Path.Combine(getSpecialFolderPath(CSIDL.CSIDL_COMMON_DESKTOPDIRECTORY), filename);
            }
            if (File.Exists(destination))
            {
               File.Delete(destination);
            }
         }

         if (_createStartMenuShortcut)
         {

            string folder;
            string destination;

            if (_installAllUsers)
            {
               folder = Path.Combine(getSpecialFolderPath(CSIDL.CSIDL_COMMON_STARTMENU), "Programs");
               folder = Path.Combine(folder, _productName);
               Directory.CreateDirectory(folder);
               destination = Path.Combine(folder, filename);
            }
            else
            {
               folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs");
               folder = Path.Combine(folder, _productName);
               Directory.CreateDirectory(folder);
               destination = Path.Combine(folder, filename);
            }

            if (File.Exists(destination))
            {
               File.Delete(destination);
            }
            
            if (Directory.Exists(folder))
            {
               try
               {
                  Directory.Delete(folder);
               }
               catch
               { }
            }
         }

         if (_createQuickLaunchShortcut)
         {
            string quickLaunch = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Microsoft\Internet Explorer\Quick Launch");
            string destination = Path.Combine(quickLaunch, filename);
            if (File.Exists(destination))
            {
               File.Delete(destination);
            }
         }
      }

      #endregion removeShortcut

      #region initializeVariables

      private void initializeVariables ()
      {
         if (Context.Parameters.ContainsKey(DESKTOP_SHORTCUT_PARAM))
         {
            _createDesktopShortcut = !string.IsNullOrEmpty(Context.Parameters[DESKTOP_SHORTCUT_PARAM]);
         }
         if (Context.Parameters.ContainsKey(SHORTCUT_MENU_SHORTCUT_PARAM))
         {
            _createStartMenuShortcut = !string.IsNullOrEmpty(Context.Parameters[SHORTCUT_MENU_SHORTCUT_PARAM]);
         }
         if (Context.Parameters.ContainsKey(QUICK_LAUNCH_SHORTCUT_PARAM))
         {
            _createQuickLaunchShortcut = !string.IsNullOrEmpty(Context.Parameters[QUICK_LAUNCH_SHORTCUT_PARAM]);
         }
         if (Context.Parameters.ContainsKey(ALL_USER_PARAM))
         {
            _installAllUsers = !string.IsNullOrEmpty(Context.Parameters[ALL_USER_PARAM]);
         }

         _installPath = Path.GetDirectoryName(Context.Parameters["assemblyPath"]);
         if (Context.Parameters.ContainsKey(PRODUCT_NAME_PARAM))
         {
            _productName = Context.Parameters[PRODUCT_NAME_PARAM];
         }

      }

      #endregion initializeVariables

      #region getSpecialFolderPath

      /// <summary>
      /// Calls the <see cref="SHGetSpecialFolderPath"/> function from the Win32 API
      /// </summary>
      /// <param name="specialFolder">The Special Folder to get.</param>
      /// <returns>The fully qualified path to the folder.</returns>
      private static string getSpecialFolderPath (CSIDL specialFolder)
      {
         System.Text.StringBuilder folder = new System.Text.StringBuilder(260);
         
         SHGetSpecialFolderPath(IntPtr.Zero, folder, (int) specialFolder, false);

         return folder.ToString();

      }

      #endregion GetSpecialFolderA

      #endregion Private Methods
   }
}